#include <iostream>
#include <cstring>

using namespace std;
// #define ONLINE_JUDGE
const int N = 1010;

int n, m, k;
int w[N][N];
int row_max[N][N], row_min[N][N];
int q[N];

void get_min(int a[], int b[], int tot)
{
    int hh = 0, tt = -1;
    for(int i = 1; i <= tot; i++)
    {
        // 判断队头是否滑出窗口 队列有效 队长超出限制
        if(hh <= tt && k <= i - q[hh]) hh++; // 出队头，每次窗口只移动一位
        while(hh <= tt && a[q[tt]] >= a[i]) tt--; // 新插入的数，比原队尾数更小，可拼接更长的队列，弹出原队尾
        q[++tt] = i; // 插入到队尾
        b[i] = a[q[hh]];
    }
}

void get_max(int a[], int b[], int tot)
{
    int hh = 0, tt = -1;
    for(int i = 1; i <= tot; i++)
    {
        // 判断队头是否滑出窗口 队列有效 队长超出限制
        if(hh <= tt && k <= i - q[hh]) hh++; // 出队头，每次窗口只移动一位
        while(hh <= tt && a[q[tt]] <= a[i]) tt--; // 新插入的数，比原队尾数更小，可拼接更长的队列，弹出原队尾
        q[++tt] = i; // 插入到队尾
        b[i] = a[q[hh]];
    }
}

signed main() 
{

    #ifdef ONLINE_JUDGE

    #else
    freopen("./in.txt","r",stdin);
    #endif
    ios::sync_with_stdio(false);
	cin.tie(0);

    cin >> n >> m >> k;

    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            cin >> w[i][j];
        

    for(int i = 1; i <= n; i++) // 横向求出最值
    {
        get_min(w[i], row_min[i], m);
        get_max(w[i], row_max[i], m);
    }

    int res = 1e9;
    int a[N], b[N], c[N]; // b最小 c最大
    int hh = 0, tt = 0;

    for(int i = k; i <= m; i++) // 竖向单调队列
    {
        for(int j = 1; j <= n; j++) a[j] = row_min[j][i];
        get_min(a, b, n);

        for(int j = 1; j <= n; j++) a[j] = row_max[j][i];
        get_max(a, c, n);

        for(int j = k; j <= n; j++) res = min(res, c[j] - b[j]);

    }

    cout << res << endl;
    return 0;
}

